﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
using System.Drawing;

namespace SpeedTestReports.Web
{

    public class XAMLGen
    {


        public string GenerateReportTree(DataTable table)
        {
            XmlDocument doc = new XmlDocument();
            //  <controls:TreeView Name="treeReports" Margin="5" SelectedItemChanged="treeReports_SelectedItemChanged">
            XAMLElement treeElement = new XAMLElement("TreeView", "controls", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls", doc);
            treeElement.SetXmlns();

            treeElement.AppendAttribute("Name", "treeReports");
            treeElement.AppendAttribute("Margin", "5,0,10,0");
            treeElement.AppendAttribute("BorderThickness", "0");

            XmlElement currentNode = null;

            if (table != null)
            {
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    if (i == 0 || !table.Rows[i]["category"].ToString().Equals(table.Rows[i - 1]["category"].ToString()))
                    {
                        //create a new node and set it to the current node.
                        //if the prev node was not null, then add it to the document
                        XmlElement headerElement = CreateTreeNode(doc, String.Empty, String.Empty, table.Rows[i]["Category"].ToString()); 
                        if (currentNode != null)
                        {
                            treeElement.Element.AppendChild(currentNode);
                        }
                        currentNode = headerElement;
                    }

                    //add a node to the current node
                    XmlElement reportElement = CreateTreeNode(doc, table.Rows[i]["id"].ToString(), "Report" + i.ToString(), table.Rows[i]["reportname"].ToString()); 
                    
                    if (currentNode != null) //there is an error if this happens
                    {
                        currentNode.AppendChild(reportElement);
                    }
                }

                treeElement.Element.AppendChild(currentNode);   //append last one created.
            }

            doc.AppendChild(treeElement.Element);
            return doc.OuterXml;
        }

        private XmlElement CreateTreeNode(XmlDocument doc, string tag, string name, string text)
        {
            XAMLElement nodeElement = new XAMLElement("TreeViewItem", "controls", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls", doc);

            nodeElement.AppendAttribute("Header", text);
            nodeElement.AppendAttribute("Tag", tag);
            nodeElement.AppendAttribute("IsExpanded", "True");

            if (!String.IsNullOrEmpty(name))
            {
                nodeElement.AppendAttribute("Name", name);
            }

            return nodeElement.Element;
        }

        public string GenerateSelectionPanel(DataTable selTable, Data data, string reportID, string sequence, SelectionValue[] selections)
        {
            //for each item in table
            //get the values
            //switch on the type   (TEXT, LIST, DATE)
            //generate the element  (textbox, combobox(list), datepicker) FOR (category, plan, releaseetc, daterange)
            //add the generate report button

            XmlDocument doc = new XmlDocument();

            if (selTable != null && data != null)
            {
                //create the first panel;
                XmlElement border = CreateBorderRectangle(doc, selTable.Rows.Count);
                XmlElement mainPanel = CreateStackPanel(doc, "Vertical", "MainSelPanel", String.Empty, "Center");
                XAMLUtil.SetXmlns(doc, ref border);

                for (int i = 0; i < selTable.Rows.Count; i++)
                {
                    string selType = selTable.Rows[i]["SelectionType"].ToString();

                    XmlElement element = null;
                    XmlElement panel = CreateStackPanel(doc, "Horizontal", String.Empty);
                    XmlElement label = CreateLabel(doc, selTable.Rows[i]["label"].ToString());

                    switch (selType.ToUpper())
                    {
                        case "TEXT":
                            {
                                bool enabled = false;   //check to see if the sequence is the current sequence, and if so, enable
                                if (Int32.Parse(sequence) == Int32.Parse(selTable.Rows[i]["sequence"].ToString())) { enabled = true; }

                                element = CreateTextNode(doc, (bool)selTable.Rows[i]["isrequired"], selTable.Rows[i]["parametername"].ToString(), 
                                    selTable.Rows[i]["defaultvalue"].ToString(), enabled);
                            }
                            break;
                        case "LIST":
                            {
                                bool enabled = false;
                                DataTable valTable = null;
                                if (Int32.Parse(sequence) == Int32.Parse(selTable.Rows[i]["sequence"].ToString())) 
                                { 
                                    enabled = true;
                                    valTable = data.GetTableByParamSql(selTable.Rows[i]["selectionsql"].ToString(), selections);
                                }
                                
                                element = CreateListNode(doc, valTable, selTable.Rows[i]["valuemember"].ToString(),
                                    selTable.Rows[i]["displaymember"].ToString(), selTable.Rows[i]["defaultvalue"].ToString(),
                                    (bool)selTable.Rows[i]["isrequired"], selTable.Rows[i]["parametername"].ToString(), enabled);
                            }
                            break;
                        case "DATE":
                            {
                                bool enabled = false;
                                if (Int32.Parse(sequence) == Int32.Parse(selTable.Rows[i]["sequence"].ToString())) { enabled = true; }

                                element = CreateDateNode(doc, (bool)selTable.Rows[i]["isrequired"], selTable.Rows[i]["parametername"].ToString(), 
                                    selTable.Rows[i]["defaultvalue"].ToString(), enabled);
                            }
                            break;
                    }
                    
                    panel.AppendChild(label);
                    panel.AppendChild(element);
                    mainPanel.AppendChild(panel);
                }

                XmlElement button = CreateButton(doc, GetBtnTextForSequence(selTable, sequence), reportID, sequence);
                mainPanel.AppendChild(button);
                border.AppendChild(mainPanel);
                doc.AppendChild(border);
            }

            return doc.InnerXml;
        }

        private string GetBtnTextForSequence(DataTable selTable, string sequence)
        {
            bool isLastSeq = true;

            if(selTable != null)
            {
                for(int i = 0; i < selTable.Rows.Count; i++)
                {
                    if(Int32.Parse(sequence) < Int32.Parse(selTable.Rows[i]["sequence"].ToString()))
                    {
                        isLastSeq = false;  //there are more sequences
                    }
                }
            }

            if (isLastSeq) { return "Submit"; }
            else { return "Next"; }
        }

        private XmlElement CreateBorderRectangle(XmlDocument doc, int childCount)
        {
            // <Rectangle Width ="400" Height="300" Stroke="#EAF4F8" StrokeThickness="2" RadiusX="20" RadiusY="20" Margin="15">
            XAMLElement element = new XAMLElement("Border", doc);

            
            //set height to childcount * 33 + 43 for a button and 40 for a 20px margin
            element.AppendAttribute("Height", ((childCount * 33) + 83).ToString());
            //set width to 400 (LIST width + label width + 40 for a 20px margin)
            element.AppendAttribute("Width", "420");
            element.AppendAttribute("BorderBrush", "#C7DDE5");
            element.AppendAttribute("BorderThickness", "2");
            element.AppendAttribute("CornerRadius", "20");
            element.AppendAttribute("Margin", "20");
  
            return element.Element;
        }

        private XmlElement CreateLabel(XmlDocument doc, string label)
        {
            return CreateLabel(doc, label, String.Empty, null, String.Empty);
        }
        private XmlElement CreateLabel(XmlDocument doc, string label, string width, Font labelFont)
        {
            return CreateLabel(doc, label, width, labelFont, String.Empty);
        }

        private XmlElement CreateLabel(XmlDocument doc, string label, string width, Font labelFont, string foreColor)
        {
            // <dataInput:Label Margin="5" Width="100" Content="Date Picker">
            XAMLElement element = new XAMLElement("Label", "dataInput", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input", doc);

            element.AppendAttribute("Margin", "5");
 
            if (!String.IsNullOrEmpty(width)) { element.AppendAttribute("Width", width); }
            else { element.AppendAttribute("Width", "100"); }

            element.AppendAttribute("Content", label);
            element.AppendAttribute("HorizontalContentAlignment", "Center");
            
            if (labelFont != null)
            {
                element.AppendAttribute("FontFamily", labelFont.FontFamily.Name);

                if (labelFont.Bold) { element.AppendAttribute("FontWeight", "Bold"); }
                else { element.AppendAttribute("FontWeight", "Normal"); }

                element.AppendAttribute("FontSize", labelFont.Size.ToString());

                if (labelFont.Italic) { element.AppendAttribute("FontStyle", "Italic"); }
                else { element.AppendAttribute("FontStyle", "Normal"); }

            }

            if (!String.IsNullOrEmpty(foreColor))
            {
                element.AppendAttribute("Foreground", foreColor);
            }

            return element.Element;
        }

        private XmlElement CreateStackPanel(XmlDocument doc, string orientation, string panelName)
        {
            return CreateStackPanel(doc, orientation, panelName, String.Empty, String.Empty);
        }

        private XmlElement CreateStackPanel(XmlDocument doc, string orientation, string panelName, string margin)
        {
            return CreateStackPanel(doc, orientation, panelName, margin, String.Empty);
        }

        private XmlElement CreateStackPanel(XmlDocument doc, string orientation, string panelName, string margin, string alignment)
        {
            // <StackPanel Orientation="Horizontal">
            XAMLElement element = new XAMLElement("StackPanel", doc);

            element.AppendAttribute("Orientation", orientation);

            if (!String.IsNullOrEmpty(panelName))
            {
                element.AppendAttribute("x:Name", panelName);
            }

            if (!String.IsNullOrEmpty(margin))
            {
                element.AppendAttribute("Margin", margin);
            }

            if (!String.IsNullOrEmpty(alignment))
            {
                element.AppendAttribute("HorizontalAlignment", alignment);
                element.AppendAttribute("VerticalAlignment", alignment);
            }

            return element.Element;
        }

        private XmlElement CreateButton(XmlDocument doc, string text, string tag, string sequence)
        {
            // <Button x:Name="btnSubmit" Width="75" Height="23" Margin="10" Content="Submit"></Button>
            XAMLElement element = new XAMLElement("Button", "dataInput", 
                "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input", doc);

            element.AppendAttribute("x:Name", "btnSubmit");
            element.AppendAttribute("Width", "75");
            element.AppendAttribute("Height", "23");
            element.AppendAttribute("Margin", "10");
            element.AppendAttribute("Content", text);
            element.AppendAttribute("Tag", tag + ":" + sequence);

            return element.Element;
        }

        private XmlElement CreateTextNode(XmlDocument doc, bool isRequired, string parameterName, string defaultValue, bool isEnabled)
        {
            // <TextBox Width="250" Margin="5" MaxLength="40" Tag="1" Text="12345 Default value">
            XAMLElement element = new XAMLElement("STTextBox", "STControls",
                "clr-namespace:SpeedTestReports;assembly=SpeedTestReports", doc);

            element.AppendAttribute("Margin", "5");
            element.AppendAttribute("MaxLength", "40");
            element.AppendAttribute("IsRequired", isRequired.ToString());
            element.AppendAttribute("ParameterName", parameterName);
            element.AppendAttribute("Text", defaultValue);
            element.AppendAttribute("IsEnabled", isEnabled.ToString());

            return element.Element;
        }

        private XmlElement CreateDateNode(XmlDocument doc, bool isRequired, string parameterName, string defaultValue, bool isEnabled)
        {
            // <controls:DatePicker Width="150" Margin="5" SelectedDate="10/04/2009" DisplayDate="10/04/2009" Tag="1">
            XAMLElement element = new XAMLElement("STDatePicker", "STControls", 
                "clr-namespace:SpeedTestReports;assembly=SpeedTestReports", doc);

            element.AppendAttribute("Width", "150");
            element.AppendAttribute("Margin", "5");

            if (defaultValue.Equals("NOW()")) { defaultValue = DateTime.Now.ToString("MM/dd/yyyy"); }
            else
            {
                DateTime dt;
                if (DateTime.TryParse(defaultValue, out dt))
                {
                    element.AppendAttribute("SelectedDate", dt.ToString("MM/dd/yyyy"));
                }
            }
            element.AppendAttribute("DisplayDate", defaultValue);
            element.AppendAttribute("IsRequired", isRequired.ToString());
            element.AppendAttribute("ParameterName", parameterName);
            element.AppendAttribute("Text", defaultValue);
            element.AppendAttribute("IsEnabled", isEnabled.ToString());

            return element.Element;
        }

        private XmlElement CreateListNode(XmlDocument doc, DataTable table, string valueColumn, string displayColumn, 
            string defaultValue, bool isRequired, string parameterName, bool isEnabled)
        {
            // <ComboBox Width="250" Margin="5" Tag="1" SelectedIndex="0">
            //        <ComboBoxItem Content="Some release" Tag="1"></ComboBoxItem>
            XAMLElement element = new XAMLElement("STComboBox", "STControls", 
                "clr-namespace:SpeedTestReports;assembly=SpeedTestReports", doc);

            element.AppendAttribute("Width", "250");
            element.AppendAttribute("Margin", "5");
            element.AppendAttribute("IsRequired", isRequired.ToString());
            element.AppendAttribute("ParameterName", parameterName);
            element.AppendAttribute("IsEnabled", isEnabled.ToString());

            if (table != null)
            {
                for (int i = 0; i < table.Rows.Count; i++)
                {
                    XmlElement itemElement = CreateListItemNode(doc, table.Rows[i][valueColumn].ToString(), table.Rows[i][displayColumn].ToString());

                    element.Element.AppendChild(itemElement);
                }

                if (table.Rows.Count > 0)
                {
                    element.AppendAttribute("SelectedIndex", "0");
                }
            }

            return element.Element;
        }

        private XmlElement CreateListItemNode(XmlDocument doc, string value, string text)
        {
            //<ComboBoxItem Content="Some release" Tag="1"></ComboBoxItem>
            XAMLElement element = new XAMLElement("ComboBoxItem", doc);

            element.AppendAttribute("Content", text);
            element.AppendAttribute("Tag", value);

            return element.Element;
        }

        public string GenerateError(string error)
        {
            //<TextBlock Text ="Reports" FontWeight="Bold" Margin="5"/>

            XmlDocument doc = new XmlDocument();

            XAMLElement textElement = new XAMLElement("TextBlock", doc);
            textElement.SetXmlns();
            textElement.AppendAttribute("Text", error);
            textElement.AppendAttribute("FontWeight", "Bold");
            textElement.AppendAttribute("Foreground", "Red");
            textElement.AppendAttribute("HorizontalAlignment", "Center");

            doc.AppendChild(textElement.Element);

            return doc.InnerXml;
        }

        public string GenerateDashboard(Data data)
        {
            //Get the dashboard report and call GenerateReport with a null selectionvalues
            long dashboardID = data.GetDashboardReportID();
            return GenerateReport(data, dashboardID.ToString(), null);
        }

        public string GenerateReport(Data data, string reportID, SelectionValue[] selValues)
        {

            //Get a table of the report sections
            DataTable sectionTable = null;
            DataTable reportTable = null;

            XmlDocument doc = new XmlDocument();
            XmlElement mainPanel = CreateStackPanel(doc, "Vertical", "ReportPanel");
            XmlElement headerPanel = CreateStackPanel(doc, "Vertical", "ReportHeaderPanel", String.Empty, "Center");
            XAMLUtil.SetXmlns(doc, ref mainPanel);

            

            if(data != null)
            {
                sectionTable = data.GetReportSections(reportID);
                reportTable = data.GetReportByID(reportID);
                
            }

            if(reportTable != null && reportTable.Rows.Count > 0)
            {
                Font headerFont = new Font("Arial", 16, FontStyle.Bold);
                int headerWidth = GetStringWidth(reportTable.Rows[0]["Header"].ToString(), headerFont);
                headerPanel.AppendChild(CreateLabel(doc, reportTable.Rows[0]["Header"].ToString(), headerWidth.ToString(), headerFont));
            }

            if (selValues != null)
            {
                Font selectionFont = new Font("Arial", 12, FontStyle.Bold);
                foreach(SelectionValue sv in selValues)
                {
                    int selectionWidth = GetStringWidth(sv.Text, selectionFont);
                    headerPanel.AppendChild(CreateLabel(doc, sv.Text, selectionWidth.ToString(), selectionFont, "Gray"));
                }
            }

            mainPanel.AppendChild(headerPanel);

            if(sectionTable != null)
            {
                for(int i = 0; i < sectionTable.Rows.Count; i++)
                {
                    string reportType = sectionTable.Rows[i]["SectionType"].ToString();

                    switch(reportType)
                    {
                        case "TABLE":
                            {

                                DataTable table = data.GetTableByParamSql(sectionTable.Rows[i]["SectionSql"].ToString(), selValues);
                                if (table != null)
                                {
                                    XmlElement panel = CreateStackPanel(doc, "Vertical", String.Empty, "0,15,0,15");
                                    XmlElement horizPanel = CreateStackPanel(doc, "Horizontal", String.Empty, "0,15,0,15", "Center");
                                    XmlElement tableElement = CreateTableReport(table, doc);

                                    horizPanel.AppendChild(tableElement);
                                    panel.AppendChild(horizPanel);  //these are required to keep the datagrid from filling the width of the scroll viewer
                                    mainPanel.AppendChild(panel);
                                }                                
                            }
                            break;
                        case "MULTITABLE":  //returns a set of tables, aligned two by two
                            {

                                DataSet set = data.GetSetByParamSql(sectionTable.Rows[i]["SectionSql"].ToString(), selValues);
                                if (set != null)
                                {
                                    foreach (DataTable table in set.Tables)
                                    {
                                       // Font theaderFont = new Font("Arial", 12, FontStyle.Bold);
                                       // XmlElement tableHeader = CreateLabel(doc, FormatHeaderName(table.TableName),
                                       //     GetStringWidth(table.TableName, theaderFont).ToString(), theaderFont);
                                        XmlElement panel = CreateStackPanel(doc, "Vertical", String.Empty, "0,15,0,15");
                                        XmlElement horizPanel = CreateStackPanel(doc, "Horizontal", String.Empty, "0,15,0,15", "Center");
                                        XmlElement tableElement = CreateTableReport(table, doc);

                                       // panel.AppendChild(tableHeader);
                                        horizPanel.AppendChild(tableElement);
                                        panel.AppendChild(horizPanel);  //these are required to keep the datagrid from filling the width of the scroll viewer
                                        mainPanel.AppendChild(panel);
                                    }
                                }
                            }
                            break;
                        case "XMLTABLE":
                            {
                                DataTable table = data.GetTableByParamSql(sectionTable.Rows[i]["SectionSql"].ToString(), selValues);

                                if (table != null && table.Rows.Count > 0)
                                {
                                    DataTable xmlTable = GetTableFromXML(table.Rows[0][0].ToString());

                                    if (xmlTable != null)
                                    {
                                        XmlElement panel = CreateStackPanel(doc, "Vertical", String.Empty, "0,15,0,15");
                                        XmlElement horizPanel = CreateStackPanel(doc, "Horizontal", String.Empty, "0,15,0,15", "Center");
                                        XmlElement tableElement = CreateTableReport(xmlTable, doc);

                                        horizPanel.AppendChild(tableElement);
                                        panel.AppendChild(horizPanel);  //these are required to keep the datagrid from filling the width of the scroll viewer
                                        mainPanel.AppendChild(panel);
                                    }
                                }
                            }
                            break;
                        case "COLUMNCHART":
                            {


                            }
                            break;
                        case "MULTICOLUMNCHART":
                            {


                            }
                            break;
                        case "BARCHART":
                            {

                            }
                            break;
                        case "MULTIBARCHART":
                            {

                            }
                            break;
                        case "PIECHART":    //if multiple rows are returned, only the first is processed
                            {
                                DataTable table = data.GetTableByParamSql(sectionTable.Rows[i]["SectionSql"].ToString(), selValues);
                                if (table != null)
                                {
                                    XmlElement panel = CreateStackPanel(doc, "Vertical", String.Empty, "0,15,0,15");
                                    XmlElement chartElement = CreatePieChart(doc, table, sectionTable.Rows[i]["Header"].ToString(), 0);

                                    panel.AppendChild(chartElement);
                                    mainPanel.AppendChild(panel);
                                } 
                            }
                            break;
                        case "MULTIPIECHART":   //arranged two wide by two long for up to the number of rows
                            {
                                DataTable table = data.GetTableByParamSql(sectionTable.Rows[i]["SectionSql"].ToString(), selValues);
                                if (table != null)
                                {
                                    XmlElement panel = CreateStackPanel(doc, "Horizontal", String.Empty, "0,15,0,15", "Center");
                                    int panelChildren = 0;

                                    for (int r = 0; r < table.Rows.Count; r++)
                                    {
                                        XmlElement chartElement = CreatePieChart(doc, table, sectionTable.Rows[i]["Header"].ToString(), r);
                                        
                                        if (chartElement != null)
                                        {
                                            if (panelChildren >= 2) 
                                            { 
                                                panel = CreateStackPanel(doc, "Horizontal", String.Empty, "0,15,0,15", "Center");
                                                panelChildren = 0; //reset
                                            }
                                            
                                            panel.AppendChild(chartElement);
                                            panelChildren++;

                                            if (panelChildren >= 2 || r == table.Rows.Count - 1) { mainPanel.AppendChild(panel); }
                                        }
                                    }
                                } 
                            }
                            break;
                        case "PROGRESSBAR": //future?
                            {

                            }
                            break;
                        case "MULTIPROGRESSBAR": //future?
                            {

                            }
                            break;
                    }
                }
            }

            doc.AppendChild(mainPanel);


            return doc.OuterXml;
        }

        private XmlElement CreateTableReport(DataTable table, XmlDocument doc)
        {
            XAMLElement gridElement = new XAMLElement("DataGrid", "data", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data", doc);
            gridElement.AppendAttribute("AutoGenerateColumns", "False");
            gridElement.AppendAttribute("IsReadOnly", "True");
            //<data:DataGrid.Columns>
            XAMLElement columnsElement = new XAMLElement("DataGrid.Columns", "data", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data", doc);
            if(table != null)
            {
                for(int i = 0; i < table.Columns.Count && i < 26; i++) //max of 26 columns
                {
                    XmlElement element = CreateColumn(FormatHeaderName(table.Columns[i].ColumnName), i, doc);
                    columnsElement.Element.AppendChild(element);
                }
            

                gridElement.Element.AppendChild(columnsElement.Element);

                XAMLElement sourceElement = new XAMLElement("DataGrid.ItemsSource", "data", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data", doc);
                XmlElement itemsElement = CreateObjectCollection(doc);

                foreach(DataRow row in table.Rows)
                {
                    itemsElement.AppendChild(CreateRow(row, doc));
                }

                sourceElement.Element.AppendChild(itemsElement);
                gridElement.Element.AppendChild(sourceElement.Element);
            }

            return gridElement.Element;
        }

        private XmlElement CreateColumn(string header, int colIndex, XmlDocument doc)
        {
            //<data:DataGridTextColumn Header="Test"  Binding="{Binding ColA}" />
            XAMLElement element = new XAMLElement("DataGridTextColumn", "data", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data", doc);

            element.AppendAttribute("Header", header);
            element.AppendAttribute("Binding", "{Binding Column" + colIndex.ToString("00") + "}");

            return element.Element;
        }

        private XmlElement CreateRow(DataRow row, XmlDocument doc)
        {
            XAMLElement element = new XAMLElement("DataRow", "STControls", "clr-namespace:SpeedTestReports;assembly=SpeedTestReports", doc);

            for(int i = 0; i < row.ItemArray.Length; i++)
            {
                element.AppendAttribute("Column" + i.ToString("00"), row.ItemArray[i].ToString());
            }

            return element.Element;
        }

        /*
        public XmlElement CreateTableReport(DataTable table, XmlDocument doc)
        {
            //calculate the size of the columns - output each row in the table
            XmlElement element = null;
            int[] maxWidths = new int[table.Columns.Count];
            int totalWidth = 0;

            //measure column headers
            for (int i = 0; i < table.Columns.Count; i++)
            {
                int width = GetStringWidth(table.Columns[i].Caption, null);

                if (maxWidths[i] < width) { maxWidths[i] = width; }
            }

            //measure table content
            for (int i = 0; i < table.Rows.Count; i++)
            {
                for(int j = 0; j < table.Columns.Count; j++)
                {
                    int width = GetStringWidth(table.Rows[i][j].ToString(), null);

                    if(maxWidths[j] < width){maxWidths[j] = width;}
                }
            }

            //get total width
            for (int w = 0; w < maxWidths.Length; w++)
            {
                totalWidth += maxWidths[w];
            }
            
            element = CreateBorder(doc, totalWidth);
            XmlElement tableElement = CreateTable(doc);
            
            //create header row
            tableElement.AppendChild(CreateHeaderRow(doc, table.Columns, maxWidths));

            for (int i = 0; i < table.Rows.Count; i++)
            {
                tableElement.AppendChild(CreateRow(doc, table.Rows[i], maxWidths));
            }

            element.AppendChild(tableElement);

            return element;
        }

        private XmlElement CreateBorder(XmlDocument doc, int width)
        {
            // <Border BorderThickness="2" BorderBrush="Gray">
            //        <ItemsControl>

            XAMLElement element = new XAMLElement("Border", doc);

            element.AppendAttribute("BorderThickness", "1");
            element.AppendAttribute("BorderBrush", "Gray");
            element.AppendAttribute("Width", width.ToString());

            return element.Element;
        }

        private XmlElement CreateTable(XmlDocument doc)
        {
            // <Border BorderThickness="2" BorderBrush="Gray">
            //        <ItemsControl>

            XmlElement element = doc.CreateElement("ItemsControl");
            return element;
        }

        private XmlElement CreateHeaderRow(XmlDocument doc, DataColumnCollection columns, int[] colWidths)
        {
            // <StackPanel Orientation="Horizontal">
            XmlElement element = CreateStackPanel(doc, "Horizontal", String.Empty);

            for (int i = 0; i < columns.Count; i++)
            {
                element.AppendChild(CreateCell(doc, FormatHeaderName(columns[i].Caption), colWidths[i], "#EAF4F8"));
            }

            return element;
        }
        */
        private string FormatHeaderName(string header)
        {
            string formattedString = String.Empty;
            string[] s = null;

            if (!String.IsNullOrEmpty(header))
            {
                s = header.Split('_');

                for (int i = 0; i < s.Length; i++)
                {
                    char[] sChars = s[i].ToCharArray();
                    sChars[0] = char.ToUpper(sChars[0]);

                    formattedString += new String(sChars) + " ";
                }
            }

            return formattedString.Trim();  //remove the trailing space
        }

        /*
        private XmlElement CreateRow(XmlDocument doc, DataRow row, int[] colWidths)
        {
            // <StackPanel Orientation="Horizontal">
            XmlElement element = CreateStackPanel(doc, "Horizontal", String.Empty);

            for (int i = 0; i < row.ItemArray.Length; i++)
            {
                element.AppendChild(CreateCell(doc, row.ItemArray[i].ToString(), colWidths[i], String.Empty));
            }

            return element;
        }
       

        private XmlElement CreateCell(XmlDocument doc, string cellText, int cellWidth, string background)
        {
            // <TextBox Width="200" Text="Some long plan name"/>
            XAMLElement element = new XAMLElement("TextBox", doc);

            element.AppendAttribute("Width", cellWidth.ToString());
            element.AppendAttribute("Text", cellText);

            if (!String.IsNullOrEmpty(background))
            {
                element.AppendAttribute("Background", background);
            }

            return element.Element;
        }
 */
        private int GetStringWidth(string s, Font measureFont)
        {
            Font defaultFont = null;
            if (measureFont == null) { defaultFont = new Font("Arial", 10); }
            else { defaultFont = measureFont; }
            Graphics g = Graphics.FromImage(new Bitmap(1, 1));
            SizeF stringSize = g.MeasureString(s, defaultFont);

            return (int)stringSize.Width + 10; //padding
        }

        private XmlElement CreatePieChart(XmlDocument doc, DataTable table, string title, int rowIndex)
        {
            // <chartingToolkit:Chart Height="200" Width="400" Title="Pie">
           // <chartingToolkit:Chart.Series>
           //     <chartingToolkit:PieSeries
           //                 IndependentValueBinding="{Binding Key}"
           //                 DependentValueBinding="{Binding Value}">
           //         <chartingToolkit:PieSeries.ItemsSource>
           //             <controlsToolkit:ObjectCollection>

            if (rowIndex >= table.Rows.Count) { return null; }
            if (table == null || table.Rows.Count < 1) { return null; }

            XmlElement chart = CreateChart(doc, table.Rows[rowIndex][0].ToString());   //the very first column should be the title.
            XmlElement chartSeries = CreateChartSeries(doc);
            XmlElement pieSeries = CreatePieSeries(doc);
            XmlElement pieItems = CreatePieSeriesItemSource(doc);
            XmlElement objectColl = CreateObjectCollection(doc);

            //sends the column name along with the cell value of the first row
            for (int i = 0; i < table.Columns.Count; i++)
            {
                if (IsTypeNumeric(table.Columns[i].DataType))
                {
                    objectColl.AppendChild(CreateGenericKeyValue(doc, FormatHeaderName(table.Columns[i].ColumnName), table.Rows[rowIndex][i].ToString()));
                }
            }

            pieItems.AppendChild(objectColl);
            pieSeries.AppendChild(pieItems);
            chartSeries.AppendChild(pieSeries);
            chart.AppendChild(chartSeries);

            return chart;
        }

        private bool IsTypeNumeric(Type dataType)
        {
            TypeCode dataTypeCode = Type.GetTypeCode(dataType);
            switch (dataTypeCode)
            {
                case TypeCode.Decimal:
                    return true;
                case TypeCode.Double:
                    return true;
                case TypeCode.Int16:
                    return true;
                case TypeCode.Int32:
                    return true;
                case TypeCode.Int64:
                    return true;
                case TypeCode.UInt16:
                    return true;
                case TypeCode.UInt32:
                    return true;
                case TypeCode.UInt64:
                    return true;
                case TypeCode.SByte:
                    return true;
                case TypeCode.Single:
                    return true;
            }

            return false;
        }

        public XmlElement CreateChart(XmlDocument doc, string title)
        {
            XAMLElement element = new XAMLElement("Chart", "chartingToolkit", 
                "clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit", doc);

            element.AppendAttribute("Height", "300");
            element.AppendAttribute("Width", "500");
            element.AppendAttribute("Title", title);
            element.AppendAttribute("Margin", "15,5,15,5");

            return element.Element;
        }

        public XmlElement CreateChartSeries(XmlDocument doc)
        {
            XmlElement element = doc.CreateElement("chartingToolkit", "Chart.Series", "clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit");
            return element;
        }

        public XmlElement CreatePieSeries(XmlDocument doc)
        {
            XAMLElement element = new XAMLElement("PieSeries", "chartingToolkit", 
                "clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit", doc);

            element.AppendAttribute("IndependentValueBinding", "{Binding Key}");
            element.AppendAttribute("DependentValueBinding", "{Binding Value}");

            return element.Element;
        }

        public XmlElement CreatePieSeriesItemSource(XmlDocument doc)
        {
            XmlElement element = doc.CreateElement("chartingToolkit", "PieSeries.ItemsSource", "clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit");
            return element;
        }

        public XmlElement CreateObjectCollection(XmlDocument doc)
        {
            XmlElement element = doc.CreateElement("controlsToolkit", "ObjectCollection", "clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Toolkit");
            return element;
        }

        public XmlElement CreateGenericKeyValue(XmlDocument doc, string key, string keyValue)
        {
           // <generic:GenericKeyValue Key="Dogs" Value="3"/>

            XAMLElement element = new XAMLElement("GenericKeyValue", "generic",
                "clr-namespace:SpeedTestReports;assembly=SpeedTestReports", doc);

            element.AppendAttribute("Key", key);
            element.AppendAttribute("Value", keyValue);

            return element.Element;
        }

        private DataTable GetTableFromXML(string xmlData)
        {
            if (!String.IsNullOrEmpty(xmlData))
            {
                DataSet set = new DataSet();
                StringReader reader = new StringReader(xmlData);
                set.ReadXml(reader);
                DataTable table = set.Tables[0].Copy();
                return table;
            }
            return null;
        }
    }

}
